import {
  call, put, all, takeLatest, select
} from 'redux-saga/effects'
import {
  ENTER_PATIENT_SESSION,
  ADD_PATIENT_MESSAGE,
  GET_PATIENT_MESSAGES,
  GET_PATIENT_MESSAGE_BY_ID,
  GET_CONSULTATION_IN_CHATROOM,
  GET_ACTIVE_SESSION,
  SET_AUDIO_PLAYED,
} from '@ACTIONS/chat'
import {
  UPDATE_ACTIVE_PATIENT_SESSION,
  REDUCED_CHAT_NUMBER,
  SET_TAB_BAR_BADGE
} from '@ACTIONS/message'
import { SYNC_MY_CONSULTATIONS_UNREAD } from '@ACTIONS/patient'
import { DEFAULT_TAKE } from '@CONSTANTS/common'
import api from '@API'
import { MESSAGE_TYPE, PARTICIPANT_ROLE } from '@CONSTANTS/chat'

import {
  getSessionsList, getCurrentSessionId, getCurrentSession, getMessagesList
} from './dataSelect'

const updateSession = function* updateSession(newMsg) {
  try {
    const currentSession = yield select(getCurrentSession)
    const { SessionId } = currentSession || {}

    if (!SessionId) return
    const sessionsLists = yield select(getSessionsList)
    const msg = newMsg.Message
    const pid = msg?.Participants?.[0]?.PatientId
    const uid = msg?.Participants?.[1]?.DoctorId
    const oldSession = sessionsLists.find(item => item.patient.pid === pid && item.doctor?.uid === uid)
    if (!oldSession) return
    yield put({
      type: UPDATE_ACTIVE_PATIENT_SESSION.REQUEST,
      updateSession: { ...oldSession, NewMessageCounts: 0, last: msg }
    })
  } catch (e) {
    yield put({
      type: UPDATE_ACTIVE_PATIENT_SESSION.FAILURE
    })
  }
}

const getConsultationInChatRoom = function* getConsultationInChatRoom(action) {
  try {
    const { consultationId, sessionId } = action
    const currentSessionId = yield select(getCurrentSessionId)
    const currentSession = yield select(getCurrentSession)
    const currConId = currentSession?.Consultation?.ConsultationId
    if (currentSessionId === sessionId || consultationId === currConId) {
      yield put({ type: ENTER_PATIENT_SESSION.REQUEST, ConsultationId: consultationId })
    }
  } catch (error) {
    yield put({ type: GET_CONSULTATION_IN_CHATROOM.FAILURE, error })
  }
}

const getDoctorAdviceMessage = function getDoctorAdviceMessage(session = {}) {
  const { LatestMessages, Consultation } = session
  if (!(Array.isArray(LatestMessages) && LatestMessages.length)) {
    return session
  }
  const newLatestMessages = [...LatestMessages]
  const doctorAdviceIndex = newLatestMessages.findIndex(item => item?.MessageType === MESSAGE_TYPE.DoctorAdvice)
  if (doctorAdviceIndex === -1) {
    return session
  }
  const doctorAdviceMessage = newLatestMessages[doctorAdviceIndex]
  newLatestMessages[doctorAdviceIndex] = {
    ...doctorAdviceMessage,
    consultation: Consultation,
  }
  return {
    ...session,
    LatestMessages: newLatestMessages,
  }
}

const enterSession = function* enterSession(action) {
  try {
    const { SessionId, ConsultationId } = action
    const postData = { Take: DEFAULT_TAKE }
    if (ConsultationId) {
      postData.ConsultationId = ConsultationId
    } else {
      postData.SessionId = [SessionId]
    }
    const requestApi = ConsultationId ? api.enterSessionByConsultationId : api.enterSessionById
    let session = yield call(requestApi, postData)
    const { Consultation } = session
    if (Consultation) {
      const [sessionData] = yield all([
        call(getDoctorAdviceMessage, session),
      ])
      session = sessionData
    }
    const { Participants } = session
    const sessionList = yield select(getSessionsList)

    yield put({ type: SYNC_MY_CONSULTATIONS_UNREAD, consultationId: ConsultationId || Consultation?.ConsultationId })
    yield put({ type: ENTER_PATIENT_SESSION.SUCCESS, session, participants: Participants })

    const oldSession = sessionList.find(item => item.SessionId === session.SessionId)
    if (!oldSession || oldSession.NewMessageCounts <= 0) return
    yield put({ type: REDUCED_CHAT_NUMBER.SUCCESS, NewMessageCounts: oldSession.NewMessageCounts })
    yield put({ type: SET_TAB_BAR_BADGE.REQUEST })
  } catch (error) {
    yield put({ type: ENTER_PATIENT_SESSION.FAILURE, error })
  }
}


const addMessage = function* addMessage(action) {
  const { message, isReceived } = action
  let newMsg = message
  const {
    preViewId, sessionId, messageId, extension, isPicture
  } = message
  let requestParams = message
  if (isPicture) {
    requestParams = {
      SessionId: sessionId,
      PictureFileName: `${messageId}.${extension}`,
      Type: 'Image'
    }
  }
  try {
    newMsg = yield call(api.createMessage, requestParams)
    yield put({
      type: ADD_PATIENT_MESSAGE.SUCCESS,
      newMsg,
      preViewId,
      isReceived
    })
    yield updateSession(newMsg)
  } catch (error) {
    const { falureMsg, resend } = message
    yield put({
      type: ADD_PATIENT_MESSAGE.FAILURE,
      error,
      falureMsg,
      resend
    })
  }
}

const getMessages = function* getMessages(action) {
  try {
    const { sessionId, take = DEFAULT_TAKE } = action
    const preList = yield select(getMessagesList)
    const realSkip = preList.length
    const result = yield call(api.getMessages, { sId: sessionId, skip: realSkip, take })
    yield put({ type: GET_PATIENT_MESSAGES.SUCCESS, list: result.Messages || [] })
  } catch (error) {
    yield put({ type: GET_PATIENT_MESSAGES.FAILURE, error })
  }
}
const getChatMessageById = function* getChatMessageById(action) {
  try {
    const { messageId } = action
    const currentSessionId = yield select(getCurrentSessionId)
    const activeSessionMessages = yield select(getMessagesList)
    const index = activeSessionMessages.findIndex(item => item?._id === messageId)
    if (!currentSessionId || index !== -1) {
      return
    }
    const message = yield call(api.getMessageById, { mId: messageId })
    yield put({ type: GET_PATIENT_MESSAGE_BY_ID.SUCCESS, message: message.Message })
  } catch (error) {
    yield put({ type: GET_PATIENT_MESSAGE_BY_ID.FAILURE, error })
  }
}
const setAudioPlayed = function* setAudioPlayed(action) {
  try {
    const { id } = action
    yield call(api.setAudioPlayed, { MessageId: id })
    yield put({ type: SET_AUDIO_PLAYED.SUCCESS, id })
  } catch (error) {
    yield put({ type: SET_AUDIO_PLAYED.FAILURE, error })
  }
}
export default function* rootSaga() {
  yield all([
    takeLatest(ENTER_PATIENT_SESSION.REQUEST, enterSession),
    takeLatest(ADD_PATIENT_MESSAGE.REQUEST, addMessage),
    takeLatest(GET_PATIENT_MESSAGES.REQUEST, getMessages),
    takeLatest(GET_PATIENT_MESSAGE_BY_ID.REQUEST, getChatMessageById),
    takeLatest(GET_CONSULTATION_IN_CHATROOM.REQUEST, getConsultationInChatRoom),
    takeLatest(SET_AUDIO_PLAYED.REQUEST, setAudioPlayed),
  ])
}
